package com.stock.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.stock.annotation.RoleEnum;
import com.stock.annotation.Roles;
import com.stock.entity.*;
import com.stock.service.IStockDataService;
import com.stock.service.IStockNameService;
import com.stock.util.GetCurrentTime;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;

import static com.stock.config.WebConfig.*;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author admin
 * @since 2023-04-11
 */
@RestController
@RequestMapping("/stockData")
public class StockDataController {
    @Autowired
    IStockDataService stockDataService;
    @Autowired
    IStockNameService stockNameService;
    @Autowired
    GetCurrentTime getCurrentTime;

    @Roles(RoleEnum.Admin)
    @ApiOperation("添加股票数据，同时会自动添加股票名称信息")
    @PostMapping("/add")
    public Result add(MultipartFile file) throws Exception {
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null || !originalFilename.endsWith(".txt")) {
            return Result.error(null, "文件需要为txt文件");
        }
        InputStream inputStream = file.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "gbk"));
        String firstLine = reader.readLine();

        QueryWrapper<StockName> wrapper = new QueryWrapper<>();
        String stockId = firstLine.substring(0, 6);
        wrapper.eq("stock_id", stockId);
        StockName stockName = stockNameService.getOne(wrapper);
        String name = "";

        if (stockName == null) {
            stockName = new StockName();
            stockName.setStockId(stockId);
            name = firstLine.substring(7, 12);
            if (name.endsWith("日")) {
                name = name.replace("日", "");
            }
            name = name.replace(" ", "");
            stockName.setStockName(name.trim());
            stockName.setCreateTime(getCurrentTime.getCurrentTimeByDay());
            stockNameService.save(stockName);
        }

        file.transferTo(new File(LOCAL_BASE_PATH + "tempData__" + name + ".txt"));
        Thread.sleep(300);
        Runtime runtime = Runtime.getRuntime();
        String command = "python " + LOCAL_BASE_PATH + SCRIPT + "NewCal.py " + name;
        try {
            String[] commands = {"cmd", "/c", command};
            runtime.exec(commands);
        } catch (IOException e) {
            e.printStackTrace();
            return Result.error(null, "数据添加出错");
        }

        QueryWrapper<StockData> stockDataQueryWrapper = new QueryWrapper<>();
        stockDataQueryWrapper.eq("stock_id", stockId);
        stockDataService.remove(stockDataQueryWrapper);

        // 去除第二行
        reader.readLine();
        String line = reader.readLine();
        String[] splits = line.split("\t");

        ArrayList<StockData> stockDataList = new ArrayList<>();
        while (splits.length > 6) {
            StockData stockData = new StockData();
            stockData.setStockId(stockName.getStockId());
            stockData.setStockDate(splits[0]);
            stockData.setStartPrice(Double.valueOf(splits[1]));
            stockData.setHighPrice(Double.valueOf(splits[2]));
            stockData.setLowPrice(Double.valueOf(splits[3]));
            stockData.setEndPrice(Double.valueOf(splits[4]));
            stockData.setDealNumber(Long.valueOf(splits[5]));
            stockData.setDealMoney(Double.valueOf(splits[6]));
            stockData.setCreateTime(getCurrentTime.getCurrentTimeByDay());
            stockDataList.add(stockData);

            line = reader.readLine();
            splits = line.split("\t");
        }
        stockDataService.saveBatch(stockDataList);

        return Result.success(null, "股票数据添加成功");
    }

    @ApiOperation("获取股票基本数据")
    @PostMapping("/getBasicData")
    public Result getBasicData(@RequestBody Map<String, String> map) {
        String stockId = map.get("stockId");
        String startDate = map.get("startDate");
        String endDate = map.get("endDate");
        QueryWrapper<StockData> wrapper = new QueryWrapper<>();
        wrapper.eq("stock_id", stockId).between("stock_date", startDate, endDate);
        return Result.success(stockDataService.list(wrapper), "股票基本数据获取成功");
    }

    @ApiOperation("获取股票均线数据")
    @PostMapping("/getAverageData")
    public Result getAverageData(@RequestBody Map<String, String> map) throws Exception {
        String stockName = map.get("stockName");
        String startDate = map.get("startDate");
        String endDate = map.get("endDate");

        String fileName = LOCAL_BASE_PATH + "MA__" + stockName + ".txt";
        File file = new File(fileName);
        if (!file.exists()) {
            if (!file.createNewFile()) {
                return Result.error(null, "数据获取出错");
            }
        }

        Runtime runtime = Runtime.getRuntime();
        String command = "python " + LOCAL_BASE_PATH + SCRIPT + "GenerateMAData.py " + stockName + " " + startDate + " " + endDate;
        try {
            String[] commands = {"cmd", "/c", command};
            Process exec = runtime.exec(commands);
            if (exec.waitFor() == 0) {
                ArrayList<AverageData> averageDataList = new ArrayList<>();
                BufferedReader reader = new BufferedReader(new InputStreamReader(Files.newInputStream(Paths.get(fileName))));
                String line = reader.readLine();
                String[] splits = line.split("\t");
                while (splits.length > 6) {
                    AverageData averageData = new AverageData();
                    averageData.setStockDate(splits[0]);
                    averageData.setM5(Double.valueOf(splits[1]));
                    averageData.setM10(Double.valueOf(splits[2]));
                    averageData.setM20(Double.valueOf(splits[3]));
                    averageData.setM30(Double.valueOf(splits[4]));
                    averageData.setM60(Double.valueOf(splits[5]));
                    averageData.setM120(Double.valueOf(splits[6]));
                    averageData.setM250(Double.valueOf(splits[7]));
                    averageDataList.add(averageData);
                    line = reader.readLine();
                    if (line == null) {
                        break;
                    }
                    splits = line.split("\t");
                }
                return Result.success(averageDataList, "股票均线数据获取成功");
            }
            return Result.error(null, "数据获取出错");
        } catch (IOException e) {
            e.printStackTrace();
            return Result.error(null, "数据获取出错");
        }
    }

    @ApiOperation("最小二乘法及随机森林法获取股票收盘价预测数据")
    @PostMapping("/getPredictData")
    public Result getPredictData(@RequestBody Map<String, String> map) throws Exception {
        String stockName = map.get("stockName");
        String predictType = map.get("predictType");
        String[] predictTypes = new String[]{"S", "M", "L", "SM", "ML", "SML"};
        if (Arrays.stream(predictTypes).noneMatch(s -> Objects.equals(s, predictType))) {
            return Result.error(null, "预测类型错误");
        }

        String algorithmType = map.get("algorithmType");
        String[] algorithmTypes = new String[]{"LeastSquares", "RandomForest"};
        if (Arrays.stream(algorithmTypes).noneMatch(s -> Objects.equals(s, algorithmType))) {
            return Result.error(null, "算法类型暂不支持，目前只支持：" + Arrays.toString(algorithmTypes));
        }

        String fileName = LOCAL_BASE_PATH + DATA + stockName;

        Runtime runtime = Runtime.getRuntime();
        String command = "python " + LOCAL_BASE_PATH + SCRIPT + algorithmType + ".py " + fileName + ".xls";
        try {
            String[] commands = {"cmd", "/c", command};
            Process exec = runtime.exec(commands);
            if (exec.waitFor() == 0) {
                ArrayList<EndPrice> endPriceList = new ArrayList<>();
                BufferedReader reader = new BufferedReader(new InputStreamReader(Files.newInputStream(Paths.get(fileName + "__" + predictType + ".txt"))));
                String line = reader.readLine();
                String[] splits = line.split("\t");
                while (splits.length > 2) {
                    EndPrice endPrice = new EndPrice();
                    endPrice.setStockDate(splits[0]);
                    endPrice.setOriginPrice(Double.valueOf(splits[1]));
                    endPrice.setPredictPrice(Double.valueOf(splits[2]));
                    endPriceList.add(endPrice);
                    line = reader.readLine();
                    if (line == null) {
                        break;
                    }
                    splits = line.split("\t");
                }
                return Result.success(endPriceList, "最小二乘法获取股票收盘价预测数据成功");
            }
            return Result.error(null, "数据获取出错");
        } catch (IOException e) {
            e.printStackTrace();
            return Result.error(null, "数据获取出错");
        }
    }
}
